#!/usr/bin/python

"""Simple utility to count the number of words in a file.

Usage:
  words.py --count --filename input_file
  - will output individual words sorted alphabetically with the number of their
    occurences.
  - Example:
    abba 127
    the 342

  words.py --topcount --filename input_file
  - will sort the same output by the number of occurences and list only top 20.
"""
import optparse
import sys

def MakeDict(text):
  """Prepares a dictionary that contains words and the number of their
    occurance.

  Takes input string, turns it into list of strings (words).
    Then creates a dictionary which will contain all the  words and number of
    their occurences.

  Args:
    text: A string, the text in which we want to count occurences.

  Returns:
    A dictionary where keys are strings, words from the text and values are
      integers representing the number of their occurences.
   """
  text = text.lower()
  word_list = text.split()
  word_count = {}
  for word in word_list:
    if word in word_count:
      word_count[word] += 1
    else:
      word_count[word] = 1
  return word_count

def Count(word_count):
  """Shows all words with number of their occurences in alphabeticall order.

  Args:
    word_count: A dictionary with words as keys and number of their occurences
      as values, like the one produced by MakeDict().

  Returns:
    A string of words and their occurences in alphabetical order.
  """
  list_of_words = word_count.keys()
  list_of_words.sort()
  result = ''
  for key in list_of_words:
    result = "%s\n %s : %s" %(result, key, word_count[key])
  return result

def GetTheSecond(pair):
  """Gets the second component from tuple.

  Args:
    pair: Tuple containing word as first component and number of it occurance
      as second component.

  Returns:
    A number - the second components from given tuple.
  """
  return pair[1]

def Topcount(word_count):
  """Finds top 20 most common words and number of their occurences.

  Args:
    word_count: Dictionary with words as keys and number of their occurences
      as values.

  Returns:
    A string of top 20 most common words and number of their occurences.
  """
  pairs = word_count.items()
  pairs.sort(key=GetTheSecond, reverse=True)
  result = ''
  for pair in pairs[:20]:
    result = "%s\n %s : %d" %(result, pair[0], pair[1])
  return result

def CheckFlags(count, topcount, filename):
  """Check if all required arguments are given.

  Args:
    count: A boolean specified by the user as --count.
    topcount: A boolean specified by the user as --topcount.
    filename: A string specified by user after --filename.

  Returns:
    A boolean, True if all the required arguments are given.
  """
  if not count and not topcount:
    return False
  if not filename:
    return False
  return True

def main():
  """Function with which we execute actions in this module."""
  parser = optparse.OptionParser()
  parser.add_option('--count', action='store_true',
    dest='count', help='print all words and their number of occurences'
    'sorted alphabetically ')
  parser.add_option('--topcount', action='store_true',
    dest='topcount', help='print the top 20 most common words')
  parser.add_option('--filename', action='store', type='string',
    dest='filename', help='input file')
  (options, unused_args) = parser.parse_args()
  try:
    input_file = open(options.filename, 'r')
  except IOError:
    print 'cannot open given file'
    sys.exit(1)
  text = input_file.read()
  word_count = MakeDict(text)
  if not CheckFlags(options.count, options.topcount, options.filename):
    print 'You must enter all flags.'
    parser.print_help()
    sys.exit(1)
  if options.count:
    print Count(word_count)
  if options.topcount:
    print Topcount(word_count)


if __name__ == '__main__':
  main()
